/*
 * td3.cpp
 *
 *  Created on: 31 janv. 2012
 *      Author: guillaume
 */

#include "td3.hpp"
#include "td2.hpp"


void amr(double* x, unsigned int p, unsigned int niveau, FILE* file){

	assert((((p & -p) xor p) == 0)  &&  (p != 0) && "P ,n'est pas une puissance de 2");
	unsigned int p_recusrif = p;
	//FILE* file = fopen("debug.txt", "w");

	for(unsigned int n = 0; n < niveau; n++ ){

		analyse_97_lifting(x, p_recusrif, file);
		p_recusrif /= 2;
	}

	for(unsigned int i = 0; i< p; i++) {

		// std::cout << "Coef num "<<  i << " : " << x[i] << std::endl;
		if(file != NULL) fprintf (file, "%e\n",x[i]);
	}
}

void iamr(double* x, unsigned int p, unsigned int niveau, FILE* file){

	assert((((p & -p) xor p) == 0)  &&  (p != 0) && "P ,n'est pas une puissance de 2");

	p /= pow(2,niveau);

	for(unsigned int n = 0; n < niveau; n++ ){


		synthese_97_lifting(x, p, NULL);
		p *= 2;

	}

	for(unsigned int i = 0; i< p/2; i++) {

		// std::cout << "Coef num "<<  i << " : " << x[i] << std::endl;
		if(file != NULL) fprintf (file, "%e\n",x[i]);
	}
}

double minSousBande(double *x, unsigned int p){

	double min = 999999999;
	for(unsigned n =0; n < p; n++){

		if(x[n] < min) min = x[n];

	}

	return min;
}

double maxSousBande(double * x, unsigned int p){
	double max = 0;
	for(unsigned n =0; n < p; n++){

		if(x[n] > max) max = x[n];
	}

	return max;
}

double moyenneSousBande(double* x, unsigned int p){
	double moyenne = 0;
	for(unsigned n =0; n < p; n++){

		moyenne += x[n];
	}
	moyenne /= p;

	return moyenne;
}

void AMRStatistiques(double* x, unsigned int p, unsigned int niveau){

	FILE* file;
	int offset = 0;
	file = fopen("AMR_stat_test.txt", "a");

	p /= pow(niveau ,2);

	fprintf (file, "Minimum, Maximum et Moyenne pour AMR de niveau %d \n", niveau);
	fprintf (file, "Min sous bande 1 %f\n" ,minSousBande(x+ offset, p));
	fprintf (file, "Max sous bande 1 %f\n" ,maxSousBande(x+ offset, p));
	fprintf (file, "Moy sous bande 1 %f\n" ,moyenneSousBande(x + offset, p));
	fprintf (file, "\n");

	offset +=  p;

	for(unsigned int n = 0; n < niveau; n++){
		fprintf (file, "Min sous bande %d %f\n",n+2 ,minSousBande(x+offset, p));
		fprintf (file, "Max sous bande %d %f\n" ,n+2, maxSousBande(x+ offset, p));
		fprintf (file, "Moy sous bande %d %f\n" ,n+2 ,moyenneSousBande(x + offset, p));
		fprintf (file, "\n");

		offset += p;
		p *= 2;
	}

	fclose(file);
}

void analyse2D_97(double * m, unsigned int p){
	FILE* file = NULL;
	int x = sqrt(p),y = sqrt(p);

	for(unsigned int cpt=0; cpt<y; cpt++){
		 analyse_97_lifting(m + (cpt*x), x, file);
	}

	double * & ml = m;

	// On fait un miroir parce que le filtre biorthogonal fait en fonction des lignes

	symetrie_miroir(ml, x, y);

	for(unsigned int cpt=0; cpt<y; cpt++){
			 analyse_97_lifting(ml + (cpt*y), y, file);
	}

	double * & md = ml;
	symetrie_miroir(md, x, y);



}void synthese2D_97(double * m, unsigned int p){
	FILE* file = NULL;
	int x = sqrt(p),y = sqrt(p);

	for(unsigned int cpt=0; cpt<y; cpt++){
		 synthese_97_lifting(m + (cpt*x), x, file);

	}

	double * & ml = m;

	// On fait un miroir parce que le filtre biorthogonal fait en fonction des lignes

	symetrie_miroir(ml, x, y);

	for(unsigned int cpt=0; cpt<y; cpt++){
		 synthese_97_lifting(ml + (cpt*y), y, file);
	}

	double * & md = ml;
	symetrie_miroir(md, x, y);


}

void symetrie_miroir(double * matrice, unsigned int x, unsigned int y ) {

	double * temp = new double[x*y];

	for(unsigned int j = 0; j<y; j++  ){
		for(unsigned int i=0; i<x; i++){

			temp[j + i*x ] = matrice[ j*y + i];

		}
	}

	memcpy(matrice, temp, sizeof(double) *x*y);
}
